﻿// Programmer: JR Padfield
// Description: 
// Version: 1
// Date: 

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Input;
using TheWorldLibrary.Input;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TheWorldLibrary.Controls
{
    public class TextBox : DrawableGameComponent
    {
        private Texture2D txtboxTexture;
        private Texture2D cursor;

        private SpriteFont spriteFont;
        private SpriteBatch spriteBatch;
        bool isActive;
        bool readOnly;
        bool isChat;
        private Rectangle bounds;
        private StringBuilder chatText;
        private List<string> lines;
        private int lineCount = 0;

        private string text;
        Keys[] keysToCheck = new Keys[] {
            Keys.A, Keys.B, Keys.C, Keys.D, Keys.E,
            Keys.F, Keys.G, Keys.H, Keys.I, Keys.J,
            Keys.K, Keys.L, Keys.M, Keys.N, Keys.O,
            Keys.P, Keys.Q, Keys.R, Keys.S, Keys.T,
            Keys.U, Keys.V, Keys.W, Keys.X, Keys.Y,
            Keys.Z, Keys.Back, Keys.Space, Keys.NumPad0,
            Keys.NumPad1, Keys.NumPad2, Keys.NumPad3,
            Keys.NumPad4, Keys.NumPad5, Keys.NumPad6,
            Keys.NumPad7, Keys.NumPad8, Keys.NumPad9, Keys.D1};

        Vector2 cursorPosition;
        Vector2 textPosition;
        Vector2 textboxPosition;

        TimeSpan blinkTime;
        bool blink;

        #region Properties

        public string Text
        {
            get { return text; }
            set { text = value; }
        }

        public Vector2 Position
        {
            get { return textboxPosition; }
            set
            {
                textboxPosition = value;
                SetTextPosition();
                SetBounds();
            }
        }

        public void SetBounds()
        {
            Bounds = new Rectangle((int)Position.X, (int)Position.Y, txtboxTexture.Width, txtboxTexture.Height);
        }

        private void SetTextPosition()
        {
            cursorPosition = new Vector2(
                textboxPosition.X + 5,
                textboxPosition.Y + 5);
            textPosition = new Vector2(
                textboxPosition.X + 5,
                textboxPosition.Y + 5);
        }

        public int Height
        {
            get { return txtboxTexture.Height; }
        }

        public int Width
        {
            get { return txtboxTexture.Width; }
        }

        public Rectangle Bounds
        {
            get { return bounds; }
            set { bounds = value; }
        }

        public bool IsActive
        {
            get { return isActive; }
            set { isActive = value; }
        }

        public bool ReadOnly
        {
            get { return readOnly; }
            set { readOnly = value; }
        }

        public bool IsChat
        {
            get { return isChat; }
            set { isChat = value; }
        }

        public List<string> Lines
        {
            get { return lines; }
            set { lines = value; }
        }

        #endregion

        #region Constructor

        public TextBox(Game game, SpriteFont spriteFont, Texture2D textBoxTexture, Texture2D cursorTexture, SpriteBatch spBatch)
            : base(game)
        {
            spriteBatch = spBatch;
            this.spriteFont = spriteFont;
            txtboxTexture = textBoxTexture;
            cursor = cursorTexture;

            textboxPosition = new Vector2(Position.X, Position.Y);
            cursorPosition = new Vector2(
                textPosition.X + 5,
                textPosition.Y + 5);
            textPosition = new Vector2(
                textboxPosition.X + 5,
                textboxPosition.Y + 5);
            blink = false;
            text = "";
            isActive = false;
            readOnly = false;
            isChat = false;
            chatText = new StringBuilder();
            lines = new List<string>();
            for (int i = 0; i <= 8; i++)
            {
                lines.Add(null);
            }
        }

        #endregion

        #region XNA Methods

        public override void Initialize()
        {
            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            blinkTime += gameTime.ElapsedGameTime;
            if (blinkTime > TimeSpan.FromMilliseconds(500))
            {
                blink = !blink;
                blinkTime -= TimeSpan.FromMilliseconds(500);
            }

            if (IsActive)
            {
                foreach (Keys key in keysToCheck)
                {
                    if (CheckKey(key))
                    {
                        AddKeyToText(key);
                    }
                }
            }

            base.Update(gameTime);

            Vector2 textsize = spriteFont.MeasureString(text);
            cursorPosition.X = textPosition.X + textsize.X;

            // Regular text box!!!
            if (!ReadOnly)
            {
                if (ButtonState.Pressed == Mouse.GetState().LeftButton && Bounds.Contains(Mouse.GetState().X, Mouse.GetState().Y))
                {
                    isActive = true;
                }
                else if (ButtonState.Pressed == Mouse.GetState().LeftButton && !Bounds.Contains(Mouse.GetState().X, Mouse.GetState().Y))
                {
                    isActive = false;
                }
            }
            chatText.Clear();
            foreach (string s in lines)
            {
                chatText.Append(s).AppendLine();
            }

            // Chat box location!!!
            if (!ReadOnly)
            {
                if (isChat)
                {
                    // TODO: Figure out math for the offset of the mouse for the chat textbox
                }
            }
        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Draw(txtboxTexture, textboxPosition, Color.White);

            if (isActive)
            {
                if (!blink)
                    spriteBatch.Draw(cursor, cursorPosition, Color.White);
            }

            if (!readOnly)
            {
                spriteBatch.DrawString(spriteFont, text, textPosition, Color.Black);
            }
            else if (readOnly)
            {
                spriteBatch.DrawString(spriteFont, chatText.ToString(), textPosition, Color.White);
            }

            base.Draw(gameTime);
        }



        #endregion

        #region Text Box Methods

        private void AddKeyToText(Keys key)
        {
            string newChar = "";
            switch (key)
            {
                case Keys.A:
                    newChar += "a";
                    break;
                case Keys.B:
                    newChar += "b";
                    break;
                case Keys.C:
                    newChar += "c";
                    break;
                case Keys.D:
                    newChar += "d";
                    break;
                case Keys.E:
                    newChar += "e";
                    break;
                case Keys.F:
                    newChar += "f";
                    break;
                case Keys.G:
                    newChar += "g";
                    break;
                case Keys.H:
                    newChar += "h";
                    break;
                case Keys.I:
                    newChar += "i";
                    break;
                case Keys.J:
                    newChar += "j";
                    break;
                case Keys.K:
                    newChar += "k";
                    break;
                case Keys.L:
                    newChar += "l";
                    break;
                case Keys.M:
                    newChar += "m";
                    break;
                case Keys.N:
                    newChar += "n";
                    break;
                case Keys.O:
                    newChar += "o";
                    break;
                case Keys.P:
                    newChar += "p";
                    break;
                case Keys.Q:
                    newChar += "q";
                    break;
                case Keys.R:
                    newChar += "r";
                    break;
                case Keys.S:
                    newChar += "s";
                    break;
                case Keys.T:
                    newChar += "t";
                    break;
                case Keys.U:
                    newChar += "u";
                    break;
                case Keys.V:
                    newChar += "v";
                    break;
                case Keys.W:
                    newChar += "w";
                    break;
                case Keys.X:
                    newChar += "x";
                    break;
                case Keys.Y:
                    newChar += "y";
                    break;
                case Keys.Z:
                    newChar += "z";
                    break;
                case Keys.Space:
                    newChar += " ";
                    break;
                case Keys.Back:
                    if (text.Length != 0)
                        text = text.Remove(text.Length - 1);
                    return;
            }
            if (InputHandler.KeyboardState.IsKeyDown(Keys.RightShift) ||
                InputHandler.KeyboardState.IsKeyDown(Keys.LeftShift))
            {
                newChar = newChar.ToUpper();
            }
            text += newChar;
        }

        private bool CheckKey(Keys key)
        {
            return InputHandler.LastKeyboardState.IsKeyDown(key) &&
                InputHandler.KeyboardState.IsKeyUp(key);
        }

        public void Show()
        {
            Enabled = true;
            Visible = true;
        }

        public void Hide()
        {
            Enabled = false;
            Visible = false;
        }

        private int GetMouseChatLocX()
        {
            return Mouse.GetState().X - (int)Position.X;
        }

        private int GetMouseChatLocY()
        {
            return Mouse.GetState().Y - (int)Position.Y;
        }

        public String wordWrap(String text)
        {
            String line = String.Empty;
            String returnString = String.Empty;
            String[] wordArray = text.Split(' ');

            foreach (String word in wordArray)
            {
                if (spriteFont.MeasureString(line + word).Length() > Width)
                {
                    returnString = returnString + line + Environment.NewLine;
                    line = String.Empty;
                }

                line = line + word + ' ';
            }

            return returnString + line;
        }

        #region Chat Box Region

        public void AddText(string msg)
        {
            if(lines.Count >= 9)
            {
                if (lines[8] != null)
                {
                    UpdateLines();
                    chatText.Clear();
                }
            }
            else if (msg == null)
            {
                return;
            }

            for (int i = 0; i <= 8; i++)
            {
                if (lines[i] == null)
                {
                    lines[i] = wordWrap(msg);
                    lineCount++;
                    break;
                }
            }      
        }

        private void UpdateLines()
        {
            string[] updateLine = new string[10];

            for (int i = 0; i <= 8; i++)
            {
                updateLine[i] = lines[i];
            }
            lines.Clear();

            for (int i = 0; i <= 8; i++)
            {
                lines.Add(null);
            }

            for (int i = 0; i <= 8; i++)
            {
                if (i + 1 == 10)
                {
                    return;
                }
                else if(updateLine[i + 1] == null)
                {
                    return;
                }

                lines[i] = updateLine[i + 1];
            }
        }

        #endregion

        #endregion
    }
}

